﻿#include "TransferDescEx.h"

#include <DescStore/ActorDesc.h>
#include <DescStore/FashionDesc.h>
#include <DescStore/TransferDesc.h>
#include <DescStore/TransferTreeDesc.h>

TransferDescEx::TransferDescEx()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

TransferDescEx::~TransferDescEx()
{
}

int TransferDescEx::CreateInit()
{
    return 0;
}

int TransferDescEx::ResumeInit()
{
    return 0;
}

int TransferDescEx::Load()
{
    return 0;
}

int TransferDescEx::CheckWhenAllDataLoaded()
{
    m_astTransferLayerInfo.clear();
    m_astFashion.clear();
    for (int i = 0; i < (int)TransferDesc::Instance()->GetResNum(); i++)
    {
        auto pDesc = TransferDesc::Instance()->GetDescByIndex(i);
        if (pDesc == NULL) continue;

        auto pActorDesc = ActorDesc::Instance()->GetDesc(pDesc->id);
        CHECK_EXPR(pActorDesc, -1, "transfer id:{} is not match actor", pDesc->id);

        pDesc->prof = pActorDesc->job;

        for (int k = 0; k < (int)pDesc->transfer_id.size(); k++)
        {
            if (pDesc->transfer_id[k] > 0)
            {
                CHECK_EXPR(k < (int)pDesc->str_skin.size(), -1, "id:{}", pDesc->id);
                int iRetCode = AddTransferFashion(pDesc->transfer_id[k], pDesc->str_skin[k].array.to_vector());
                CHECK_ERR(0, iRetCode, "transfer id:{} add fashion failed!, desc id:{}", pDesc->transfer_id[k], pDesc->id);

                CHECK_EXPR(k < (int)pDesc->pre_transfer_skill.size(), -1, "id:{}", pDesc->id);
                auto pTreeDesc = TransferTreeDesc::Instance()->GetDescByTypeSkillIdTransferId(ESKILL_TALENT_TYPE_ACTIVE, pDesc->pre_transfer_skill[k], pDesc->transfer_id[k]);
                CHECK_EXPR(pTreeDesc, -1, "transfer id:{} config pre-skill:{} is invalid, desc id:{}", pDesc->transfer_id[k], pDesc->pre_transfer_skill[k], pDesc->id);
            }
        }
    }

    auto& vecTransferTree = TransferTreeDesc::Instance()->GetResDesc();
    for (int i = 0; i < (int)vecTransferTree.size(); i++)
    {
        auto& transferTree = vecTransferTree[i];

        CHECK_EXPR(IS_VALID_TRANSFER_LAYER(transferTree.pre_layer), -1, "invalid transfer layer!");

        if (transferTree.pre_layer > 0)
        {
            CHECK_EXPR(IS_VALID_TRANSFER_LAYER_POS(transferTree.pre_pos), -1, "invalid transfer layer pos!");
        }

        auto pLayerInfo = FindTransferLayerInfo(transferTree.transfer_id);
        if (!pLayerInfo)
        {
            pLayerInfo = CreateTransferLayerInfo(transferTree.transfer_id);
        }
        CHECK_EXPR(pLayerInfo, -1, "transfer layer info is fulled!");

        int iRetCode = AddLayerInfo(pLayerInfo, &transferTree);
        CHECK_RET(iRetCode, "add transfer layer info failed!");
    }

    for (int i = 0; i < (int)vecTransferTree.size(); i++)
    {
        auto& transferTree = vecTransferTree[i];

        if (transferTree.pre_layer > 0)
        {
            auto pPreDesc = GetDescByPos(transferTree.transfer_id, transferTree.pre_layer, transferTree.pre_pos);
            CHECK_EXPR(pPreDesc, -1, "id:{} invalid pre_layer:{}  layer pos:{}",transferTree.id, transferTree.pre_layer, transferTree.pre_pos);

            TransferTreeDesc::Instance()->GetDesc(pPreDesc->id)->next_id = transferTree.id;
        }

        if (transferTree.is_auto_learn)
        {
            TTransferLayerInfo* pLayerInfo = FindTransferLayerInfo(transferTree.transfer_id);
            CHECK_NULL(0, pLayerInfo);

            CHECK_EXPR(pLayerInfo->m_aiAutoNodeID.size() < pLayerInfo->m_aiAutoNodeID.max_size(), -1, "transfer id:{}  auto learn node is fulled!", transferTree.transfer_id);

            pLayerInfo->m_aiAutoNodeID.push_back(transferTree.id);
        }

        switch (transferTree.type)
        {
            case proto_ff::ESKILL_TALENT_TYPE_ACTIVE:
            case proto_ff::ESKILL_TALENT_TYPE_AOYI:
            case proto_ff::ESKILL_TALENT_TYPE_BUFF:
            {
                //CHECK_SKILL( "TransferTreeDesc", m_astDesc[i].id, m_astDesc[i].skill_id );
                break;
            }
            case proto_ff::ESKILL_TALENT_TYPE_PASSIVE:
            case proto_ff::ESKILL_TALENT_TYPE_TEXING:
            {
                break;
            }
            default:
            {
                LOGSVR_ERROR("id:" << transferTree.id << " invalid skill type:" << transferTree.type);
                return -1;
            }
        }
    }
    return 0;
}

int TransferDescEx::AddLayerInfo(TTransferLayerInfo* pLayerInfo, E_TransferTree* pstDesc)
{
    if (IS_VALID_TRANSFER_LAYER(pstDesc->layer)
        && IS_VALID_TRANSFER_LAYER_POS(pstDesc->pos))
    {
        if (pLayerInfo->m_aiNodeID[pstDesc->layer][pstDesc->pos - 1] != 0)
        {
            LOGSVR_ERROR("transferid:" << pstDesc->transfer_id << " layer:" << pstDesc->layer << " pos:" << pstDesc->pos
                << " is repeated!");
            return -1;
        }

        pLayerInfo->m_aiNodeID[pstDesc->layer][pstDesc->pos - 1] = pstDesc->id;
        pLayerInfo->m_iMaxLayer = std::max(pLayerInfo->m_iMaxLayer, pstDesc->layer);
    }

    return 0;
}

TTransferLayerInfo* TransferDescEx::FindTransferLayerInfo(int iTransferID)
{
    auto iter = m_astTransferLayerInfo.find(iTransferID);
    if (iter != m_astTransferLayerInfo.end())
    {
        return &iter->second;
    }
    return NULL;
}

TTransferLayerInfo* TransferDescEx::CreateTransferLayerInfo(int iTransferID)
{
    auto pTrans = GetTransferLayerInfo(iTransferID);
    if (pTrans == NULL && !m_astTransferLayerInfo.full())
    {
        return &m_astTransferLayerInfo[iTransferID];
    }
    return NULL;
}

const TTransferLayerInfo* TransferDescEx::GetTransferLayerInfo(int iTransferID) const
{
    auto iter = m_astTransferLayerInfo.find(iTransferID);
    if (iter != m_astTransferLayerInfo.end())
    {
        return &iter->second;
    }
    return NULL;
}

const E_TransferTree* TransferDescEx::GetDescByPos(int iTransferID, int iLayer, int iPos)
{
    const TTransferLayerInfo* pLayerInfo = GetTransferLayerInfo(iTransferID);
    CHECK_EXPR(pLayerInfo, NULL, "get tranfer layer failed! id:{}", iTransferID);

    CHECK_EXPR(IS_VALID_TRANSFER_LAYER(iLayer), NULL, "invalid transfer layer!");

    CHECK_EXPR(IS_VALID_TRANSFER_LAYER_POS(iPos), NULL, "invalid transfer layer pos!");

    return TransferTreeDesc::Instance()->GetDesc(pLayerInfo->m_aiNodeID[iLayer][iPos - 1]);
}

E_Transfer* TransferDescEx::GetDescByProf(int iProf) const
{
    for (int i = 0; i < (int)TransferDesc::Instance()->GetResNum(); i++)
    {
        auto pDesc = TransferDesc::Instance()->GetDescByIndex(i);
        if (pDesc == nullptr) continue;
        if (pDesc->prof == iProf)
        {
            return pDesc;
        }
    }
    return nullptr;
}

int TransferDescEx::AddTransferFashion(int iTransferID, const std::vector<int>& vecFashionIds)
{
    CHECK_EXPR(m_astFashion.size() < m_astFashion.max_size(), -1, "m_astFastion space not enough, iTransferID:{}", iTransferID);
    auto iter = m_astFashion.find(iTransferID);
    CHECK_EXPR(iter == m_astFashion.end(), -1, "m_astFastion has iTransferID:{}", iTransferID);
    auto& fashion = m_astFashion[iTransferID];
    fashion.m_iTransferID = iTransferID;
    for (size_t i = 0; i < vecFashionIds.size(); i++)
    {
        auto pFashionDesc = FashionDesc::Instance()->GetDesc(vecFashionIds[i]);
        CHECK_EXPR(pFashionDesc, -1, "Transfer id:{}  cfg invalid fasion id:{}", iTransferID, vecFashionIds[i]);
        CHECK_EXPR(pFashionDesc->type - 1 >= 0 && pFashionDesc->type - 1 < proto_ff::enFashionType_MAX, -1, "invalid fashion type:{}", pFashionDesc->type);

        fashion.m_aiFashionID[pFashionDesc->type] = vecFashionIds[i];
        LOGSVR_TRACE("add transfer id:" << iTransferID << "  fasion id:" << vecFashionIds[i]);
    }
    return 0;
}

int TransferDescEx::GetTransferFashion(int iTransferID, int iIndex) const
{
    auto pData = GetTransferFashion(iTransferID);
    if (pData)
    {
        if (iIndex >= 0 && iIndex < proto_ff::enFashionType_MAX)
        {
            return pData->m_aiFashionID[iIndex];
        }
    }
    return 0;
}

const TTransferFashion* TransferDescEx::GetTransferFashion(int iTransferID) const
{
    auto iter = m_astFashion.find(iTransferID);
    if (iter != m_astFashion.end())
    {
        return &iter->second;
    }
    return nullptr;
}

bool TransferDescEx::IsProfAndTransferMatch(int iProf, int iTranferID) const
{
    auto pDesc = GetDescByProf(iProf);
    if (pDesc)
    {
        if (pDesc->init_transfer_id == iTranferID)
        {
            return true;
        }

        for (int i = 0; i < (int)pDesc->transfer_id.size(); ++i)
        {
            if (pDesc->transfer_id[i] == iTranferID)
            {
                return true;
            }
        }
    }

    return false;
}
